iT邦幫忙

2024 iThome 鐵人賽

DAY 9
0
Software Development

做一支專屬自己學校的課程評價 LINE Bot 吧!系列 第 9

[Day 09] 在 views.py 接收使用者訊息、篩選資料表及回覆 TextSendMessage 訊息-陽春麵版

  • 分享至 

  • xImage
  •  

先求有再求好,我們先以陽春麵版的機器人文字查詢與回覆方式,帶各位引入門與了解邏輯,下一篇會介紹漂漂亮亮版,讓你的機器人看起來很有格局~

新增數筆評價資料

這邊提供三筆範例課程評價資料供讀者使用,欄位依序為類型、課名、老師名、投稿者、內容、投稿學期,其內容為真實投稿內容改編,而其中兩筆評價描寫的課程名稱相同,以便進行程式教學。

先在 http://127.0.0.1:8000/admin/chatbot/course/ 或是直接進入後台 courses Table 手動新增三筆資料,讓資料庫開始有了生氣~

定義需求

  • 使用者輸入「老師名稱-課程名」格式進行查詢,例如: 「王小明-海洋生命科學導論」
  • 如果有對應的評價就回覆,若沒有則不回覆

為什麼沒有對應的評價,會選擇以不回應處理,而不是回應「查不到」呢?因為在做小生物 LINE Bot 的時候,我們發現到許多學生會將機器人作為備忘錄使用,如果不斷回覆反而造成使用困擾,所以在這邊選擇了不回覆,當然,這只是觀察使用者使用習慣後的一種選擇,在這裡也提醒開發者,除了技術外,使用者體驗也是非常重要的

views.py 接收訊息與引入資料表進行搜尋回覆

  1. 引入資料類別與移除原貓貓程式碼:先將 hulolo > hulolo > models.py 的資料表類別引入,再將 handle_message 函式原本貓貓的內容做移除,首先從變數 event 中取得使用者所發送的文字:
    # 此檔案位置: hulolo > chatbot > views.py
    from .models import *
    @parser.add(MessageEvent, message=TextMessage)
    def handle_message(event):
        user_message = event.message.text  # 取得使用者發送的文字
    
  2. 判別訊息是否為查詢評價,並進行分割處理:再來我們藉由 - 判定使用者想要進行評價搜尋,因為此時搜尋評價的規則是「王小明-海洋生命科學導論」,無論如何都會有 -,並以 - 為界做字串分割,前者為老師,後者為課名:
    # 接續上一步程式碼
    if "-" in user_message:
        teacher_name = user_message.split("-")[0]
        course_name = user_message.split("-")[1]
    
  3. 取關鍵字搜尋資料表內容:我們將得到的 teacher_name 以及 course_name ,以此當作關鍵字進行搜尋,這邊會使用到一個資料庫 ORM 查詢的方式,Course.objects.filter 代表的是從 Course 類別/資料表中進行過濾,過濾的條件則是希望欄位 teacher_name 等於 teacher_name;欄位 course_name 等於 course_name,注意兩變數雖然一樣但是代表意義不同,前者是來自 models.py field 所命名,後者則是來自第 2 步所宣告的變數:
    # 接續上一步程式碼
    filtered_courses = Course.objects.filter(teacher_name=teacher_name, course_name=course_name)[:5]
    

    LINE 官方文件規定一次回覆最多為 5 則,因此這邊取的資料為最多前 5 筆。

  4. 判別資料表內容與整理回覆格式:查詢的結果就會裝在 filtered_courses,可以透過 exists() 判斷裡面有沒有查詢到,若有就可以準備打包給使用者,這邊使用了迴圈是因為可能搜尋到的評價不只一則:
    # 接續上一步程式碼
    if filtered_courses.exists():
        messages = []
        for course in filtered_courses:
            messages.append(TextSendMessage(
            text=f"""
            課程: {course.course_name}\
            評價: {course.feedback_content}
            """))
    
  5. 將要回覆的訊息放到 line_bot_api.reply_message 準備回覆:
    # 接續上一步程式碼
    line_bot_api.reply_message(
        event.reply_token,
        messages  #回覆所有 messages 陣列中的值
    )      
    
  6. 我在最後 else 加上了 print("Empty"),這樣會一查無此評價就可以在 Terminal 顯示,讓開發的你有一些安全感,至少不是壞了,其 handle_message 所有程式碼如下:
    @parser.add(MessageEvent, message=TextMessage)
    def handle_message(event):
        user_message = event.message.text # 取得使用者發送的文字
        if "-" in user_message:
            teacher_name = user_message.split("-")[0]
            course_name = user_message.split("-")[1]
            filtered_courses = Course.objects.filter(teacher_name=teacher_name, course_name=course_name)[:5]
            if filtered_courses.exists():
                messages = []
                for course in filtered_courses:
                    messages.append(TextSendMessage(
                        text=f"""課程: {course.course_name}\
                        評價: {course.feedback_content}
                        """))
    
                line_bot_api.reply_message(
                    event.reply_token,
                    messages  
                )         
            else:
                print("Empty")
    

結果

當輸入 王小明-海洋生命科學導論 就會得到一筆訊息回覆,輸入 吳小峰-特殊教育學生評量 則會收到兩筆訊息回覆,這樣就對啦~
https://ithelp.ithome.com.tw/upload/images/20240923/20151510DSScQ4HyTw.png

再往前一點點

  • @parser.add(MessageEvent, message=TextMessage) 是一種監聽的裝飾器,每當使用者發送 TextMessage 文字類型訊息的時候,就會請裝飾器下面的 handle_message 做處理,換言之也可以監聽圖片、影片、聲音等類型。
  • 在範例中 Course.objects.filter 與沒有介紹的 Course.objects.get 都是常用的取得資料方式,前者無論有無結果都會回傳;而 .objects.get只允許一個結果回來,如果多個就會跳 Exception,適用在預期結果只有唯一,例如 id 或是身分證字號具有唯一性的搜尋條件,其效率會較高。
  • line_bot_api.reply_message 中的 event.reply_token 是每一封使用者發送訊息時,LINE 轉傳過來的識別碼,需要在數秒內 帶著要回的訊息與識別碼回覆給 LINE 伺服器,使用者才會成功收到我們要給的訊息,且識別碼只能使用一次。可以想看看如果識別碼不會過期的話,那我們就可以一直一直吵對方了,這樣很快就天下大亂了: D

覆盤

在這篇文章中,我們學會了:

  • 利用 objects.filter 篩選資料表的方式
  • event.message.text 接收使用者訊息與解讀的方法
  • 要回覆訊息的 messages 可以是一個陣列,最多五個回覆給使用者
  • 最基本的關鍵字搜尋流程: 解讀訊息->資料庫篩選->回覆訊息給使用者
  • 利用 TextSendMessage 回覆訊息
  • Day 09 原始碼

上一篇
[Day 08] 遷移與利用 admin.py 顯示後台課程評價資料表
下一篇
[Day 10] 使用 FlexSendMessage 讓回覆訊息變成-金箔陽春麵版
系列文
做一支專屬自己學校的課程評價 LINE Bot 吧!20
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言